﻿/**
 * 任务管理
 *
 * 创建时间：2021年8月5日
 * 作者：李述铜
 * 联系邮箱: 527676163@qq.com
 */
#include "comm/cpu_instr.h"
#include "core/task.h"
#include "tools/klib.h"
#include "tools/log.h"
#include "cpu/irq.h"
#include "os_cfg.h"

static task_manager_t task_manager;
static uint32_t idle_task_stack[IDLE_STACK_SIZE];	// 空闲任务堆栈

static int tss_init (task_t * task, uint32_t entry, uint32_t esp) {
    // 为TSS分配GDT
    irq_state_t state = irq_enter_protection();
    int tss_sel = gdt_alloc_desc();
    if (tss_sel < 0) {
        log_printf("alloc tss failed.\n");
        return -1;
    }

    segment_desc_set(tss_sel, (uint32_t)&task->tss, sizeof(tss_t), 
            SEG_P_PRESENT | SEG_DPL0 | SEG_TYPE_TSS);
    irq_leave_protection(state);
    // tss段初始化
    kernel_memset(&task->tss, 0, sizeof(tss_t));
    task->tss.eip = entry;
    task->tss.esp = task->tss.esp0 = esp;
    task->tss.ss0 = KERNEL_SELECTOR_DS;
    task->tss.eip = entry;
    task->tss.eflags = EFLAGS_DEFAULT | EFLAGS_IF;
    task->tss.es = task->tss.ss = task->tss.ds
            = task->tss.fs = task->tss.gs = KERNEL_SELECTOR_DS;   // 暂时写死
    task->tss.cs = KERNEL_SELECTOR_CS;    // 暂时写死
    task->tss.iomap = 0;

    task->tss_sel = tss_sel;
    return 0;
}

/**
 * @brief 初始化任务
 */
int task_init (task_t *task, const char * name, uint32_t entry, uint32_t esp) {
    ASSERT(task != (task_t *)0);

    tss_init(task, entry, esp);

    task->state = TASK_CREATED;
    task->time_slice = TASK_TIME_SLICE_DEFAULT;
    task->slice_ticks = TASK_TIME_SLICE_DEFAULT;
    kernel_strcpy(task->name, name);
    list_node_init(&task->all_node);
    list_node_init(&task->run_node);
    irq_state_t state = irq_enter_protection();
    task_set_ready(task);
    list_insert_last(&task_manager.list_node_all,&task->all_node);
    irq_leave_protection(state);

    // uint32_t *pesp = (uint32_t *)esp;
    // if(pesp){
    //     *(--pesp) = entry;
    //     *(--pesp) = 0;
    //     *(--pesp) = 0;
    //     *(--pesp) = 0;
    //     *(--pesp) = 0;
    //     task->stack = pesp;
    // }
    return 0;
}

void task_set_ready(task_t *task)
{
    list_insert_last(&task_manager.list_node_run,&task->run_node);
    task->state = TASK_READY;
}

/**
 * @brief 切换至指定任务
 */
void simple_switch (uint32_t ** from, uint32_t * to);

void task_switch_from_to (task_t * from, task_t * to) {
    switch_to_tss(to->tss_sel);
    // simple_switch(&from->stack,to->stack);
}

void task_first_init (void){
    task_init(&task_manager.first_task,"first_task", 0, 0);
    write_tr(task_manager.first_task.tss_sel);
    task_manager.curr_task = &task_manager.first_task;
}

task_t * task_first_task (void) {
    return &task_manager.first_task;
}

void task_set_block(task_t * task)
{
    list_remove(&task_manager.list_node_run, &task->run_node);
}

task_t * task_current (void) {
    return task_manager.curr_task;
}

int sys_yield (void){
    if(task_manager.list_node_run.count > 1)
    {
        task_t * curr = task_current();
        
        task_set_block(curr);
        task_set_ready(curr);

        task_dispatch();
    }
    return 0;
}

/**
 * @brief 空闲任务
 */
static void idle_task_entry (void) {
    for (;;) {
        hlt();
    }
}

void task_manager_init (void){
    list_init(&task_manager.list_node_all);
    list_init(&task_manager.list_node_run);
    list_init(&task_manager.list_node_sleep);
    task_init(&task_manager.idle_task, "idle task"
            ,(uint32_t)idle_task_entry
            ,(uint32_t)(idle_task_stack + IDLE_STACK_SIZE)
    );
    task_manager.curr_task = (task_t *)0;
    
}

static task_t * task_next_run (void){
    if (list_count(&task_manager.list_node_run) == 0) {
        return &task_manager.idle_task;
    }
    list_node_t * next_node = list_first(&task_manager.list_node_run);
    return offset_to_parent(next_node, task_t, run_node);
}


void task_dispatch (void){
    task_t * to = task_next_run();
    if(to != task_manager.curr_task)
    {
        task_t *from = task_manager.curr_task;
        task_manager.curr_task = to;
        to->state = TASK_RUNNING;
        task_switch_from_to(from,to);
    }
}

void task_time_tick(void)
{
    task_t * task = task_current();
    irq_state_t state = irq_enter_protection();
    if(--task->slice_ticks == 0)
    {
        task->slice_ticks = task->time_slice;  // 重置递减时间片计数
        task_set_block(task);       // 将任务从就绪队列中删除
        task_set_ready(task);       // 将任务插入到就绪队列的末尾
        task_dispatch();            // 重新分配任务
    }
    list_node_t* curr = list_first(&task_manager.list_node_sleep);
    while(curr)
    {
        list_node_t * next = list_node_next(curr);
        task_t *task = offset_to_parent(curr, task_t, run_node);
        if(--task->sleep_ticks == 0)
        {
            task_set_wakeup(task);
            task_set_ready(task);
        }
        curr = next;
    }
    task_dispatch();
    irq_leave_protection(state);
}

void task_set_wakeup(task_t * task){
    list_remove(&task_manager.list_node_sleep, &task->run_node);
}
void task_set_sleep(task_t *task, uint32_t sleep){
    if(sleep < 1)
    {
        return ;
    }
    task->sleep_ticks = sleep;
    task->state = TASK_SLEEP;
    list_insert_last(&task_manager.list_node_sleep, &task->run_node);
    return ;
}

void sys_msleep(uint32_t ticks)
{
    if (ticks < OS_TICK_MS) {
        ticks = OS_TICK_MS;
    }
    task_t * task = task_current();
    irq_state_t state = irq_enter_protection();
    task_set_block(task);
    task_set_sleep(task_manager.curr_task, (ticks + (OS_TICK_MS - 1))/ OS_TICK_MS); 
    task_dispatch();
    irq_leave_protection(state);
}